Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Sep 28, 2025

When users attempt to set a non-git directory as an active project, GitButler now provides a user-friendly experience with an option to initialize a git repository directly from the error dialog.

Problem

Previously, when users tried to open a project in a directory that wasn't a git repository, they would encounter a generic error message with no clear path forward. This created friction in the onboarding experience and left users unsure how to proceed.

Solution

This PR implements a complete solution that:

  1. Detects non-git repositories - Enhanced set_project_active() to recognize when git2::Repository::open() fails due to missing git structure (error codes: NotFound, Invalid, Config)

  2. Provides custom error classification - Added new NonGitRepository error code to the error system that maps from backend to frontend

  3. Offers guided remediation - Shows a special warning toast with an "Initialize Repository" button instead of a generic error

  4. Safely initializes git repositories - New init_git_repository() Tauri command with comprehensive safety checks:

    • Validates directory exists and is writable
    • Prevents overwriting existing git repositories
    • Includes proper error handling and logging
  5. Seamless user experience - After successful initialization, automatically retries loading the project

User Flow

User opens non-git directory
     ↓
GitButler detects missing .git structure
     ↓
Warning toast: "Not a Git repository - Would you like to initialize one?"
     ↓
User clicks "Initialize Repository"
     ↓
Git repo created safely with validation
     ↓
Success message + automatic project loading

Technical Implementation

Backend Changes:

  • Added NonGitRepository variant to gitbutler_error::error::Code
  • Enhanced error detection in set_project_active() with multiple git2 error code mapping
  • New init_git_repository() command with write permission validation
  • Comprehensive error handling for edge cases

Frontend Changes:

  • Added error code mapping in knownErrors.ts
  • Enhanced project layout error handling to detect specific error code
  • Interactive toast with action button for git initialization
  • Service method integration for backend communication

Safety & Validation

  • Path validation: Ensures target is an existing, writable directory
  • Existing repository protection: Prevents initialization in directories that are already git repositories
  • Permission checks: Validates write access before attempting initialization
  • Error boundaries: Comprehensive error handling for all failure modes

This change maintains full backward compatibility while significantly improving the user experience for a common onboarding scenario. Users can now seamlessly convert any directory into a GitButler-compatible project with a single click.

Original prompt

When setting the active project to a non-git repository, attache a custom Code to the error. That error is recogoniced when adding the project, and a popup displays that offers the user to initialise a repository at that directory, before retrying.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copy link

vercel bot commented Sep 28, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
gitbutler-web Ignored Ignored Preview Sep 30, 2025 0:21am

@Copilot Copilot AI changed the title [WIP] When setting the active project to a non-git repository, attache a custom Code to the error. That error is recogoniced when adding the project, and a popup displays that offers the user to initialise a repository at that directory, before retrying. Add custom error handling for non-git repositories with initialization option Sep 28, 2025
@Copilot Copilot AI requested a review from Byron September 28, 2025 18:46
Copilot finished work on behalf of Byron September 28, 2025 18:46
@github-actions github-actions bot added rust Pull requests that update Rust code @gitbutler/desktop labels Sep 29, 2025
@Byron Byron force-pushed the copilot/fix-39e85eac-2ac8-479c-9252-27cba9b10ed2 branch from 3af024b to cd0e2c1 Compare September 29, 2025 04:01
Copy link
Collaborator

@Byron Byron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I processed the PR to be usable, but it needs frontend work.

The basis already works and isn't bad at all.

Screenshot 2025-09-29 at 05 58 37
Screen.Recording.2025-09-29.at.06.02.53.mov

But to truly work, it needs some finesse that I unfortunately cannot provide.
Maybe a low-hanging fruit to pick if it's not too complicated to actually do.

CC @PavelLaptev and @estib-vega

PS: the PR is based on this message on Discord.

Comment on lines 217 to 219
#[tauri::command]
#[instrument(err(Debug))]
pub fn init_git_repository(path: String) -> Result<(), Error> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function trivially would have to be moved to but-api.

Comment on lines 166 to 172
message:
'The selected directory is not a Git repository. Would you like to initialize one?',
style: 'warning',
extraAction: {
label: 'Initialize Repository',
onClick: async (dismiss) => {
try {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the main difficulty: initialising and re-adding the project from here to get a project id.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me take a look!

@Byron Byron added the UX/UI Focusing on user satisfaction, usability, and overall experience label Sep 29, 2025
@Byron Byron requested a review from estib-vega September 29, 2025 04:06
@estib-vega
Copy link
Contributor

@Byron, just to clarify:

That warning pop-up is shown when the backend hits: https://github.com/gitbutlerapp/gitbutler/blob/master/crates/gitbutler-project/src/controller.rs#L100

My understanding is that this is a catch-all response for failing to open a directory. So, just wanted to confirm that that can only mean that the repository is not initialized. Otherwise, we'd be offering a 'false' fix action.

@Byron
Copy link
Collaborator

Byron commented Sep 29, 2025

My understanding is that this is a catch-all response for failing to open a directory. So, just wanted to confirm that that can only mean that the repository is not initialized. Otherwise, we'd be offering a 'false' fix action.

That's a very good point - right now it's very 'rough'.

Can I add this improvement as second pass on yours?
One would have to match on gix::open to fail in a particular way, and associate this with a unique enum variant to trigger the "not initialised" popup only when nothing else went wrong.

❯ gix free discover
open (strict) .:
        "." does not appear to be a git repository

        Caused by:
            Missing HEAD at '.git/HEAD'
open (lenient) .:
        "." does not appear to be a git repository

        Caused by:
            Missing HEAD at '.git/HEAD'

discover from .:
        Could not find a git repository in '.' or in any of its parents

discover (plumbing) from .:
        Could not find a git repository in '.' or in any of its parents

Error: At least one operation failed

@estib-vega estib-vega force-pushed the copilot/fix-39e85eac-2ac8-479c-9252-27cba9b10ed2 branch from cd0e2c1 to a860421 Compare September 29, 2025 10:34
Copilot AI and others added 5 commits September 30, 2025 13:43
Move the method for initializing a repository by its path to the shared API module, so that the server can have this as well
When adding a non-git repostory and then chossing to initialize that, the application should correcly add the project
@estib-vega estib-vega force-pushed the copilot/fix-39e85eac-2ac8-479c-9252-27cba9b10ed2 branch from a860421 to c15f679 Compare September 30, 2025 11:57
@estib-vega
Copy link
Contributor

@Byron This effort might need more planning that probably intended. Let me know what you think:

The option to initialize a directory as a git repository will lead for the project to be added, but the next thing that the user will see is an error page:

Screenshot 2025-09-30 at 13 55 39

The issue is that no project without a remote can be added to the application (yet) and so it explodes

@estib-vega
Copy link
Contributor

We might want to add more methods to address this gracefully, from the application, but that seems to increase the scope of this as bit too much.

At this point, we need to design this flow correctly (because this state can already be encountered regardless of whether this changes make it into the application)

I'll tag here @PavelLaptev, since we need to make some time to work this flow (IMO we can get away with just displaying a splash screen asking the user to add a remote to their repository from the terminal and pushing).

@estib-vega
Copy link
Contributor

In its current state, I'll avoid merging this, since we'd be adding a big pathway into scary cul-de-sac

@Byron
Copy link
Collaborator

Byron commented Sep 30, 2025

I see 😅.

I'd say we salvage what's there, I improve the error handling so it's precise, and we merge it as is knowing that soon this will be covered by single-branch mode.

Probably once we have improved onboarding to not enforce setting the target branch anyway, we'd want to have an E2E test for this extended flow:

  • as a new user with onboarding completed
  • add non-git directory
  • initialise it here
  • see the newly initialised repo in single-branch mode

Wonderful :).

Also definitely CC @krlvi and @mtsgrd just to be sure this goes in the right direction.

@estib-vega
Copy link
Contributor

see the newly initialised repo in single-branch mode

I'd wait for this to be implemented before merging this, though.

I wouldn't like to trade a warning pop-up for a non-actionable full-screen error

@Byron
Copy link
Collaborator

Byron commented Sep 30, 2025

Alright - I got carried away. I will add the error selection now and you can take it over again.

@Byron
Copy link
Collaborator

Byron commented Sep 30, 2025

Here is the commit - and now that I tried it myself I totally understand why we should not just merge this.
The experience isn't very satisfying just now.

Screen.Recording.2025-09-30.at.14.20.06.mov

@PavelLaptev
Copy link
Contributor

Thanks @estib-vega Ill check this out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@gitbutler/desktop @gitbutler/ui rust Pull requests that update Rust code UX/UI Focusing on user satisfaction, usability, and overall experience
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants